/*
 * 描          述:  <描述>
 * 修  改   人:  Administrator
 * 修改时间:  2018年6月4日
 * <修改描述:>
 */
package com.tx.core.util;

import java.beans.PropertyDescriptor;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Index;
import javax.persistence.JoinColumn;
import javax.persistence.OneToMany;
import javax.persistence.OrderBy;
import javax.persistence.Table;
import javax.persistence.Transient;

import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.map.LRUMap;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeanWrapperImpl;
import org.springframework.core.convert.TypeDescriptor;

import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.tx.core.exceptions.util.AssertUtils;

import io.swagger.annotations.ApiModelProperty;
import io.swagger.v3.oas.annotations.media.Schema;

/**
 * JPA解析工具类<br/>
 * <功能详细描述>
 *
 * @author Administrator
 * @version [版本号, 2018年6月4日]
 * @see [相关类/方法]
 * @since [产品/模块版本]
 */
public class TableInfoUtils {

	/** 缓存表字段 */
	private static Map<Class<?>, List<TableColumnInfo>> parseTableColumnsCache = new LRUMap<>(1000);

	/** 缓存表字段映射 */
	private static Map<Class<?>, Map<String, TableColumnInfo>> parseTableColumnMapCache = new LRUMap<>(5000);

	/** 缓存表索引 */
	private static Map<Class<?>, List<TableIndexInfo>> parseTableIndexesCache = new LRUMap<>(1000);

	/** 缓存主键字段 */
	private static Map<Class<?>, TableColumnInfo> parsePKTableColumnCache = new LRUMap<>(1000);

	/** 缓存主键字段集 */
	private static Map<Class<?>, List<TableColumnInfo>> parsePKTableColumnsCache = new LRUMap<>(5000);

	/** 缓存表名 */
	private static Map<Class<?>, String> parseTableNameCache = new LRUMap<>(5000);

	/**
	 * 解析对象表名<br/>
	 * <功能详细描述>
	 *
	 * @param beanType
	 * @return [参数说明]
	 * @return String [返回类型说明]
	 * @throws throws [异常类型] [异常说明]
	 * @see [类、类#方法、类#成员]
	 */
	public static String parseTableName(Class<?> beanType) {
		AssertUtils.notNull(beanType, "beanType is null.");
		if (parseTableNameCache.containsKey(beanType) && !parseTableNameCache.get(beanType).isEmpty()) {
			return parseTableNameCache.get(beanType);
		}

		// 没有注解的时候默认使用类名当作表名
		String tableName = beanType.getSimpleName();
		// 如果存在javax注解中的Entity读取其Name
		// org.hibernate.annotations.Entity该类中不含有表名，不进行解析
		if (beanType.isAnnotationPresent(Entity.class)) {
			String entityName = beanType.getAnnotation(Entity.class).name();
			if (!StringUtils.isEmpty(entityName)) {
				tableName = entityName.toUpperCase();
			}
		}
		if (beanType.isAnnotationPresent(Table.class)) {
			// 如果含有注解：javax.persistence.Table
			String annoTableName = beanType.getAnnotation(Table.class).name();
			if (!StringUtils.isEmpty(annoTableName)) {
				tableName = annoTableName.toUpperCase();
			}
		}
		if (beanType.isAnnotationPresent(TableName.class)) {
			// 如果含有注解：javax.persistence.Table
			String annoTableName = beanType.getAnnotation(TableName.class).value();
			if (!StringUtils.isEmpty(annoTableName)) {
				tableName = annoTableName.toUpperCase();
			}
		}

		parseTableNameCache.put(beanType, tableName);
		return tableName;
	}

	/**
	 * 解析JPA有关索引的注解
	 *
	 * @param beanType
	 * @return
	 */
	public static List<TableIndexInfo> parseTableIndexes(Class<?> beanType) {
		AssertUtils.notNull(beanType, "beanType is null.");

		if (parseTableIndexesCache.containsKey(beanType) && parseTableIndexesCache.get(beanType) != null) {
			return parseTableIndexesCache.get(beanType);
		}

		List<TableIndexInfo> resList = new ArrayList<>();
		if (beanType.isAnnotationPresent(Table.class)) {
			Table tableAnno = beanType.getAnnotation(Table.class);
			if (tableAnno.indexes() != null && tableAnno.indexes().length > 0) {
				for (Index i : tableAnno.indexes()) {
					if (StringUtils.isNotEmpty(i.name()) && StringUtils.isNotEmpty(i.columnList())) {
						TableIndexInfo index = new TableIndexInfo(i, beanType);
						resList.add(index);
					}
				}
			}
		}
		List<TableColumnInfo> columns = parseTableColumns(beanType);
		for (TableColumnInfo c : columns) {
			if (c.getTypeDescriptor().hasAnnotation(Index.class)) {
				Index i = c.getTypeDescriptor().getAnnotation(Index.class);
				TableIndexInfo index = new TableIndexInfo(i, c);
				resList.add(index);
			}
		}

		parseTableIndexesCache.put(beanType, resList);
		return resList;
	}

	/**
	 * 返回属性字段与字段之间的映射关系<br/>
	 *
	 * @param beanType
	 * @return
	 */
	public static Map<String, TableColumnInfo> parseTableColumnMap(Class<?> beanType) {
		AssertUtils.notNull(beanType, "beanType is null.");

		if (parseTableColumnMapCache.containsKey(beanType) && parseTableColumnMapCache.get(beanType) != null) {
			return parseTableColumnMapCache.get(beanType);
		}

		List<TableColumnInfo> columns = parseTableColumns(beanType);
		Map<String, TableColumnInfo> resMap = new HashMap<>();
		columns.stream().forEach(c -> {
			resMap.put(c.getPropertyName(), c);
		});
		parseTableColumnMapCache.put(beanType, resMap);
		return resMap;
	}

	/**
	 * 解析表字段<br/>
	 *
	 * @param beanType
	 * @return
	 */
	public static List<TableColumnInfo> parseTableColumns(Class<?> beanType) {
		AssertUtils.notNull(beanType, "beanType is null.");

		if (parseTableColumnsCache.containsKey(beanType) && parseTableColumnsCache.get(beanType) != null) {
			return parseTableColumnsCache.get(beanType);
		}

		// 解析jpa属性
		List<TableColumnInfo> columns = new ArrayList<>();
		// objBW.getPropertyTypeDescriptor("parent").hasAnnotation(JsonIgnore.class)
		BeanWrapper bw = new BeanWrapperImpl(beanType);
		boolean hasPrimaryKey = false;// 是否存在主键
		for (PropertyDescriptor pd : BeanUtils.getPropertyDescriptors(beanType)) {
			String propertyName = pd.getName();
			TypeDescriptor td = bw.getPropertyTypeDescriptor(propertyName);
			if (TableInfoUtils.isIgnoreProperty(pd, td)) {
				continue;
			}

			TableColumnInfo jpaColumnInfo = new TableColumnInfo(pd, td);
			boolean primaryKey = TableInfoUtils.isPrimaryKey(pd, td);// 判断是否为主键
			if (primaryKey) {
				hasPrimaryKey = true;
			}
			jpaColumnInfo.setPrimaryKey(primaryKey);

			columns.add(jpaColumnInfo);
		}

		if (!hasPrimaryKey) {
			// 如果没有主键：判断是否有id,code这样的字段
			// 如果有id
			for (TableColumnInfo col : columns) {
				if (StringUtils.equalsIgnoreCase("id", col.getPropertyDescriptor().getName())) {
					col.setPrimaryKey(true);
					hasPrimaryKey = true;
					break;
				}
			}
		}
		if (!hasPrimaryKey) {
			// 如果没有主键：判断是否有id,code这样的字段
			// 如果有code
			for (TableColumnInfo col : columns) {
				if (StringUtils.equalsIgnoreCase("code", col.getPropertyDescriptor().getName())) {
					col.setPrimaryKey(true);
					hasPrimaryKey = true;
					break;
				}
			}
		}

		Collections.sort(columns, COLUMN_COMPARATOR);

		parseTableColumnsCache.put(beanType, columns);
		return columns;
	}

	/**
	 * 解析表主键字段<br/>
	 * 当主键字段不存在，或超过一个时抛出异常 主键超过一个 或是主键值指定了多个字段的场景
	 *
	 * @param beanType
	 * @return
	 */
	public static TableColumnInfo parsePKTableColumn(Class<?> beanType) {
		AssertUtils.notNull(beanType, "beanType is null.");

		if (parsePKTableColumnCache.containsKey(beanType) && parsePKTableColumnCache.get(beanType) != null) {
			return parsePKTableColumnCache.get(beanType);
		}

		// 解析jpa属性
		List<TableColumnInfo> columns = parseTableColumns(beanType);
		List<TableColumnInfo> pkColumns = new ArrayList<>();
		columns.stream().forEach(c -> {
			if (c.isPrimaryKey()) {
				pkColumns.add(c);
			}
		});

		AssertUtils.notEmpty(pkColumns, "无主键字段.type:{}", new Object[] { beanType });
		AssertUtils.isTrue(pkColumns.size() == 1, "主键字段不唯一.type:{}", new Object[] { beanType });

		parsePKTableColumnCache.put(beanType, pkColumns.get(0));
		return pkColumns.get(0);
	}

	/**
	 * 解析表主键字段<br/>
	 *
	 * @param beanType
	 * @return
	 */
	public static List<TableColumnInfo> parsePKTableColumns(Class<?> beanType) {
		AssertUtils.notNull(beanType, "beanType is null.");

		if (parsePKTableColumnsCache.containsKey(beanType) && parsePKTableColumnsCache.get(beanType) != null) {
			return parsePKTableColumnsCache.get(beanType);
		}
		// 解析jpa属性
		List<TableColumnInfo> columns = parseTableColumns(beanType);
		List<TableColumnInfo> pkColumns = new ArrayList<>();
		columns.stream().forEach(c -> {
			if (c.isPrimaryKey()) {
				pkColumns.add(c);
			}
		});

		parsePKTableColumnsCache.put(beanType, pkColumns);
		return pkColumns;
	}

	/**
	 * 解析表排序字段<br/>
	 *
	 * @param beanType
	 * @param columnInfos
	 * @param defaultOrderByProperties
	 * @return
	 */
	public static List<String> parseOrderBys(Class<?> beanType, List<TableColumnInfo> columnInfos,
			String... defaultOrderByProperties) {
		AssertUtils.notNull(beanType, "beanType is null.");
		AssertUtils.notEmpty(columnInfos, "columnInfos is null.");

		// 解析jpa属性
		List<String> orderBys = new ArrayList<>();
		for (TableColumnInfo columnInfo : columnInfos) {
			String orderBy = parseOrderBy(beanType, columnInfo);
			if (StringUtils.isEmpty(orderBy)) {
				continue;
			}
			orderBys.add(orderBy);
		}

		// 如果有默认的排序字段
		if (!ArrayUtils.isEmpty(defaultOrderByProperties)) {
			for (String name : defaultOrderByProperties) {
				if (StringUtils.isEmpty(name)) {
					continue;
				}
				for (TableColumnInfo columnTemp : columnInfos) {
					if (!StringUtils.equalsIgnoreCase(name, columnTemp.getPropertyName())) {
						continue;
					}
					orderBys.add(columnTemp.getColumnName() + " DESC");
				}
			}
		}

		// 如果默认的字段都不存在，则默认以主键为排序字段
		if (CollectionUtils.isEmpty(orderBys)) {
			for (TableColumnInfo columnTemp : columnInfos) {
				if (!columnTemp.isPrimaryKey()) {
					continue;
				}
				orderBys.add(columnTemp.getColumnName() + " DESC");
			}
		}
		return orderBys;
	}

	/**
	 * 解析表排序字段<br/>
	 *
	 * @param beanType
	 * @param columnInfos
	 * @param defaultOrderByPropertys
	 * @return
	 */
	public static String parseOrderBy(Class<?> beanType, List<TableColumnInfo> columnInfos,
			String... defaultOrderByPropertys) {
		AssertUtils.notNull(beanType, "beanType is null.");
		AssertUtils.notEmpty(columnInfos, "columnInfos is null.");

		// 解析jpa属性
		for (TableColumnInfo columnInfo : columnInfos) {
			String orderBy = parseOrderBy(beanType, columnInfo);
			if (!StringUtils.isEmpty(orderBy)) {
				return orderBy;
			}
		}

		// 如果有默认的排序字段
		if (!ArrayUtils.isEmpty(defaultOrderByPropertys)) {
			for (String name : defaultOrderByPropertys) {
				if (StringUtils.isEmpty(name)) {
					continue;
				}
				for (TableColumnInfo columnTemp : columnInfos) {
					if (!StringUtils.equals(name, columnTemp.getPropertyName())) {
						continue;
					}
					return columnTemp.getColumnName() + " DESC";
				}
			}
		}

		// 如果默认的字段都不存在，则默认以主键为排序字段
		for (TableColumnInfo columnTemp : columnInfos) {
			if (!columnTemp.isPrimaryKey()) {
				continue;
			}
			return columnTemp.getColumnName() + " DESC";
		}

		return null;
	}

	/**
	 * 是否忽略属性<br/>
	 *
	 * @param pd
	 * @param td
	 * @return
	 */
	public static boolean isIgnoreProperty(PropertyDescriptor pd, TypeDescriptor td) {
		AssertUtils.notNull(pd, "pd is null.");
		AssertUtils.notNull(td, "td is null.");

		// 如果属性没有同时具备Read,Write方法时则跳过该属性
		if (pd.getReadMethod() == null || pd.getWriteMethod() == null) {
			return true;
		}

		// collection,map，array,interface,annotation,abstract
		// Modifier.isAbstract(propertyType.getModifiers()) boolean等值，=true了，先修改以後再進行處理
		Class<?> propertyType = pd.getPropertyType();
		if (td.isCollection() || td.isMap() || td.isArray() || propertyType.isInterface()
				|| propertyType.isAnnotation()) {
			return true;
		}

		if (td.hasAnnotation(Transient.class)) {
			return true;
		} else if (td.hasAnnotation(java.beans.Transient.class)) {
			return true;
		} else if (td.hasAnnotation(org.springframework.data.annotation.Transient.class)) {
			return true;
		} else if (td.hasAnnotation(OneToMany.class)) {
			return true;
		} else if (td.hasAnnotation(TableField.class) && !td.getAnnotation(TableField.class).exist()) {
			// 有TableField，并且exist为false
			return true;
		}

		return false;
	}

	/**
	 * 判断属性是否为主键<br/>
	 * 通过检查属性描述器和类型描述器上是否注解了特定的主键注解来判断。<br/>
	 *
	 * @param pd 属性描述器，描述一个JavaBean的属性
	 * @param td 类型描述器，描述属性的数据类型
	 * @return boolean 返回true如果属性被标记为主键，否则返回false
	 */
	private static boolean isPrimaryKey(PropertyDescriptor pd, TypeDescriptor td) {
		// 确保传入的参数不为null
		AssertUtils.notNull(pd, "pd is null.");
		AssertUtils.notNull(td, "td is null.");

		// 检查类型描述器上是否注解了Id、org.springframework.data.annotation.Id或TableId注解
		// 如果注解存在，则表示属性为主键
		if (td.hasAnnotation(Id.class)) {
			return true;
		} else if (td.hasAnnotation(org.springframework.data.annotation.Id.class)) {
			return true;
		} else if (td.hasAnnotation(TableId.class)) {
			return true;
		}
		// 如果没有上述注解，则属性不是主键
		return false;
	}

	/**
	 * 获取字段名<br/>
	 *
	 * @param beanType
	 * @param columnInfo
	 * @return
	 */
	private static String parseOrderBy(Class<?> beanType, TableColumnInfo columnInfo) {
		AssertUtils.notNull(beanType, "beanType is null.");
		AssertUtils.notNull(columnInfo, "columnInfo is null.");
		AssertUtils.notNull(columnInfo.getTypeDescriptor(), "columnInfo.typeDescriptor is null.");

		TypeDescriptor td = columnInfo.getTypeDescriptor();
		String orderBy = null;

		// 如果readMethod上有忽略字段的注解，则跳过该字段
		if (td.hasAnnotation(OrderBy.class)) {
			OrderBy orderByAnnotation = td.getAnnotation(OrderBy.class);
			if (StringUtils.isEmpty(orderByAnnotation.value())) {
				orderBy = columnInfo.getColumnName() + " DESC";
			} else {
				orderBy = orderByAnnotation.value();
			}
			return orderBy;
		}
		if (td.hasAnnotation(org.hibernate.annotations.OrderBy.class)) {
			org.hibernate.annotations.OrderBy orderByAnnotation = td
					.getAnnotation(org.hibernate.annotations.OrderBy.class);
			if (StringUtils.isEmpty(orderByAnnotation.clause())) {
				orderBy = columnInfo.getColumnName() + " DESC";
			} else {
				orderBy = orderByAnnotation.clause();
			}
			return orderBy;
		}

		return orderBy;
	}

	/**
	 * JPA索引信息
	 */
	public static class TableIndexInfo {

		protected final Index indexAnnotation;

		/** 索引名 */
		private String indexName;

		/** 字段名 */
		private List<String> columnNames;

		/** 唯一键注解 */
		private boolean unique;

		/**
		 * 从字段上加载索引
		 *
		 * @param indexAnnotation
		 */
		public TableIndexInfo(Index indexAnnotation, TableColumnInfo column) {
			super();
			AssertUtils.notNull(indexAnnotation, "indexAnnotation is null.");
			AssertUtils.notNull(column, "column is null.");

			this.indexAnnotation = indexAnnotation;

			this.unique = this.indexAnnotation.unique();

			if (StringUtils.isEmpty(this.indexAnnotation.name())) {
				this.indexName = "IDX_" + column.getColumnName().toUpperCase();
			} else {
				this.indexName = this.indexAnnotation.name().toUpperCase();
			}

			// 字段集
			if (!StringUtils.isEmpty(this.indexAnnotation.columnList())
					&& StringUtils.splitByWholeSeparator(this.indexAnnotation.columnList(), ",").length > 0) {
				this.columnNames = Arrays
						.stream(StringUtils.splitByWholeSeparator(this.indexAnnotation.columnList(), ",")).filter(s -> {
							if (StringUtils.isEmpty(s) || StringUtils.isBlank(s)) {
								return false;
							} else {
								return true;
							}
						}).map(s -> s.trim()).collect(Collectors.toList());
			} else {
				this.columnNames = Arrays.asList(column.getColumnName());
			}
		}

		/**
		 * @param indexAnnotation
		 * @param beanType
		 */
		public TableIndexInfo(Index indexAnnotation, Class<?> beanType) {
			super();
			this.indexAnnotation = indexAnnotation;

			AssertUtils.notNull(indexAnnotation, "indexAnnotation is null.");
			AssertUtils.notEmpty(indexAnnotation.name(), "indexAnnotation.name is empty.");
			AssertUtils.notEmpty(indexAnnotation.columnList(), "indexAnnotation.columnList is empty.");

			this.indexName = this.indexAnnotation.name().toUpperCase();
			this.columnNames = Arrays.stream(StringUtils.splitByWholeSeparator(this.indexAnnotation.columnList(), ","))
					.filter(s -> {
						if (StringUtils.isEmpty(s) || StringUtils.isBlank(s)) {
							return false;
						} else {
							return true;
						}
					}).map(s -> s.trim()).collect(Collectors.toList());
		}

		public Index getIndexAnnotation() {
			return indexAnnotation;
		}

		public String getIndexName() {
			return indexName;
		}

		public void setIndexName(String indexName) {
			this.indexName = indexName;
		}

		public List<String> getColumnNames() {
			return columnNames;
		}

		public void setColumnNames(List<String> columnNames) {
			this.columnNames = columnNames;
		}

		public boolean isUnique() {
			return unique;
		}

		public void setUnique(boolean unique) {
			this.unique = unique;
		}
	}

	/**
	 * JPA字段信息<br/>
	 * <功能详细描述>
	 *
	 * @author Administrator
	 * @version [版本号, 2018年6月6日]
	 * @see [相关类/方法]
	 * @since [产品/模块版本]
	 */
	public static class TableColumnInfo {

		/** 属性描述 */
		protected final PropertyDescriptor propertyDescriptor;

		/** TypeDescriptor */
		protected final TypeDescriptor typeDescriptor;

		/** ColumnColumn */
		protected final Column columnAnnotation;

		/** TableField */
		protected final TableField columnTableFieldAnnotation;

		/** JoinColumn */
		protected JoinColumn joinColumnAnnotation;

		/**
		 * 嵌套属性描述，如果不存在嵌套属性，则该值为空
		 */
		protected PropertyDescriptor nestedPropertyDescriptor;

		/**
		 * 是否是主键: 不根据属性判断，如果不存在@Id注解时，系统将考虑采用id,或是code字段当做唯一键字段
		 */
		protected boolean primaryKey = false;

		/**
		 * <默认构造函数>
		 */
		public TableColumnInfo(PropertyDescriptor propertyDescriptor, TypeDescriptor typeDescriptor) {
			super();
			this.propertyDescriptor = propertyDescriptor;
			this.typeDescriptor = typeDescriptor;
			this.columnAnnotation = typeDescriptor.getAnnotation(Column.class);
			this.columnTableFieldAnnotation = typeDescriptor.getAnnotation(TableField.class);
			this.joinColumnAnnotation = typeDescriptor.getAnnotation(JoinColumn.class);

			if (!BeanUtils.isSimpleValueType(propertyDescriptor.getPropertyType())) {
				// 如果属性不为simpleType则使用JPA解析二级属性
				this.nestedPropertyDescriptor = parseCustomizeTypeNestedPropertyDescriptorByColumnName(
						propertyDescriptor, getColumnName());
			}
		}

		/**
		 * @return 返回 propertyDescriptor
		 */
		public PropertyDescriptor getPropertyDescriptor() {
			return propertyDescriptor;
		}

		/**
		 * @return 返回 typeDescriptor
		 */
		public TypeDescriptor getTypeDescriptor() {
			return typeDescriptor;
		}

		/**
		 * @return 返回 columnAnnotation
		 */
		public Column getColumnAnnotation() {
			return columnAnnotation;
		}

		/**
		 * @return 返回 joinColumnAnnotation
		 */
		public JoinColumn getJoinColumnAnnotation() {
			return joinColumnAnnotation;
		}

		/**
		 * @return 返回 primaryKey
		 */
		public boolean isPrimaryKey() {
			return primaryKey;
		}

		/**
		 * @param primaryKey
		 */
		public void setPrimaryKey(boolean primaryKey) {
			this.primaryKey = primaryKey;
		}

		/**
		 * 属性是否是简单类型<br/>
		 * <功能详细描述>
		 *
		 * @return [参数说明]
		 * @return boolean [返回类型说明]
		 * @throws throws [异常类型] [异常说明]
		 * @see [类、类#方法、类#成员]
		 */
		public boolean isSimpleValueType() {
			return BeanUtils.isSimpleValueType(getPropertyType());
		}

		/**
		 * 是否含有嵌套属性<br/>
		 * <功能详细描述>
		 *
		 * @return [参数说明]
		 * @return boolean [返回类型说明]
		 * @throws throws [异常类型] [异常说明]
		 * @see [类、类#方法、类#成员]
		 */
		public boolean hasNestedProperty() {
			return this.nestedPropertyDescriptor != null;
		}

		/**
		 * @return 返回 nestedPropertyDescriptor
		 */
		public PropertyDescriptor getNestedPropertyDescriptor() {
			return nestedPropertyDescriptor;
		}

		/**
		 * @return 返回 columnName
		 */
		public String getColumnName() {
			if (this.columnAnnotation != null && !StringUtils.isEmpty(columnAnnotation.name())) {
				return columnAnnotation.name();
			}
			if (this.joinColumnAnnotation != null && !StringUtils.isEmpty(joinColumnAnnotation.name())) {
				return joinColumnAnnotation.name();
			}
			return this.propertyDescriptor.getName();
		}

		/**
		 * 返回字段注释
		 *
		 * @return
		 */
		public String getComment() {
			if (this.typeDescriptor.hasAnnotation(ApiModelProperty.class)) {
				ApiModelProperty ampAnno = this.typeDescriptor.getAnnotation(ApiModelProperty.class);
				if (StringUtils.isNotEmpty(ampAnno.value())) {
					return ampAnno.value();
				}
			}
			if (this.typeDescriptor.hasAnnotation(Schema.class)) {
				Schema schemaAnno = this.typeDescriptor.getAnnotation(Schema.class);
				if (StringUtils.isNotEmpty(schemaAnno.description())) {
					return schemaAnno.description();
				}
			}
			return "";
		}

		/**
		 * 获取属性名（如果含有嵌套属性，则显示为嵌套属性）<br/>
		 * <功能详细描述>
		 *
		 * @return [参数说明]
		 * @return String [返回类型说明]
		 * @throws throws [异常类型] [异常说明]
		 * @see [类、类#方法、类#成员]
		 */
		public String getColumnPropertyName() {
			if (this.nestedPropertyDescriptor == null) {
				return this.propertyDescriptor.getName();
			} else {
				return this.propertyDescriptor.getName() + "." + this.nestedPropertyDescriptor.getName();
			}
		}

		/**
		 * 获取嵌套属性类型<br/>
		 * <功能详细描述>
		 *
		 * @return [参数说明]
		 * @return Class<?> [返回类型说明]
		 * @throws throws [异常类型] [异常说明]
		 * @see [类、类#方法、类#成员]
		 */
		public Class<?> getColumnPropertyType() {
			if (this.nestedPropertyDescriptor == null) {
				return this.propertyDescriptor.getPropertyType();
			} else {
				return nestedPropertyDescriptor.getPropertyType();
			}
		}

		/**
		 * @return 返回 nullable
		 */
		public boolean isNullable() {
			if (primaryKey) {
				// 如果为主键时必填，不能为空
				return false;
			} else {
				return (columnAnnotation == null) ? true : columnAnnotation.nullable();
			}
		}

		/**
		 * @return 返回 length
		 */
		public int getLength() {
			return (columnAnnotation == null) ? 255 : columnAnnotation.length();
		}

		/**
		 * @return 返回 precision
		 */
		public int getPrecision() {
			return (columnAnnotation == null) ? (Number.class.isAssignableFrom(getColumnPropertyType()) ? 32 : 64)
					: columnAnnotation.precision();
		}

		/**
		 * @return 返回 scale
		 */
		public int getScale() {
			return (columnAnnotation == null) ? (Number.class.isAssignableFrom(getColumnPropertyType()) ? 2 : 0)
					: columnAnnotation.scale();
		}

		/**
		 * @return 返回 unique
		 */
		public boolean isUnique() {
			return (columnAnnotation == null) ? false : columnAnnotation.unique();
		}

		/**
		 * @return 返回 insertable
		 */
		public boolean isInsertable() {
			if (this.columnAnnotation == null && this.columnTableFieldAnnotation == null) {
				return true;
			} else if (this.columnTableFieldAnnotation != null) {
				if (this.columnTableFieldAnnotation.fill() == null
						|| this.columnTableFieldAnnotation.fill() == FieldFill.DEFAULT) {
					// 这里的处理与mybatis-plus规定不一致
					return true;
				} else if (FieldFill.INSERT.equals(this.columnTableFieldAnnotation.fill())
						|| FieldFill.INSERT_UPDATE.equals(this.columnTableFieldAnnotation.fill())) {
					return true;
				} else {
					return false;
				}
			} else {
				return columnAnnotation.insertable();
			}
		}

		/**
		 * @return 返回 updatable
		 */
		public boolean isUpdatable() {
			if (this.columnAnnotation == null && this.columnTableFieldAnnotation == null) {
				return true;
			} else if (this.columnTableFieldAnnotation != null) {
				if (this.columnTableFieldAnnotation.fill() == null
						|| this.columnTableFieldAnnotation.fill() == FieldFill.DEFAULT) {
					// 这里的处理与mybatis-plus规定不一致
					return true;
				} else if (FieldFill.UPDATE.equals(this.columnTableFieldAnnotation.fill())
						|| FieldFill.INSERT_UPDATE.equals(this.columnTableFieldAnnotation.fill())) {
					return true;
				} else {
					return false;
				}
			} else {
				return columnAnnotation.updatable();
			}
		}

		/**
		 * 获取属性名<br/>
		 * <功能详细描述>
		 *
		 * @return String [返回类型说明]
		 */
		public String getPropertyName() {
			return this.propertyDescriptor.getName();
		}

		/**
		 * 获取属性类型 该方法用于获取属性的类型信息。
		 *
		 * @return Class<?> 返回属性的类型。如果属性是基本类型，则返回对应的包装类；如果是数组，则返回数组的元素类型。
		 */
		public Class<?> getPropertyType() {
			return this.propertyDescriptor.getPropertyType();
		}
	}

	/**
	 * 默认的字段比较器，用于对表格列信息进行排序。 首先，将主键列优先排序在最上方。 其次，列名包含"code"的字段会被优先排序。
	 * 接着，通过列名的首字母、长度以及列名的相似度来进一步确定排序顺序。
	 */
	public static final Comparator<TableColumnInfo> COLUMN_COMPARATOR = new Comparator<TableColumnInfo>() {
		/**
		 * 比较两个TableColumnInfo对象，确定它们的排序顺序。
		 *
		 * @param o1 第一个要比较的TableColumnInfo对象。
		 * @param o2 第二个要比较的TableColumnInfo对象。
		 * @return 如果o1应该排在o2之前返回负数，如果o1应该排在o2之后返回正数，如果它们相等返回0。
		 */
		@Override
		public int compare(TableColumnInfo o1, TableColumnInfo o2) {
			// 主键优先排序
			if (o1.isPrimaryKey()) {
				return -1;
			} else if (o2.isPrimaryKey()) {
				return 1;
			}
			// "code"字段优先级次于主键
			else if (StringUtils.equalsIgnoreCase("code", o1.getColumnName())) {
				return -1;
			} else if (StringUtils.equalsIgnoreCase("code", o2.getColumnName())) {
				return 1;
			}

			// 对剩下的字段按照特定规则进行排序
			String[] o1ColumnNameArray = splitColumeName(o1.getColumnName());
			String[] o2ColumnNameArray = splitColumeName(o2.getColumnName());
			// 首先根据首字母进行排序
			String o1ColumnI0 = o1ColumnNameArray[0];
			String o2ColumnI0 = o2ColumnNameArray[0];
			if (!StringUtils.equalsAnyIgnoreCase(o1ColumnI0, o2ColumnI0)) {
				// 当首字母不相同时，根据字长进行排序
				if (o1ColumnI0.length() != o2ColumnI0.length()) {
					return Integer.compare(o1ColumnI0.length(), o2ColumnI0.length());
				} else {
					// 长度相同时，根据字母顺序进行排序
					return o1ColumnI0.compareTo(o2ColumnI0);
				}
			} else {
				// 首字母相同时，进一步比较列名长度或列名细分后的长度
				if (o1ColumnNameArray.length == o2ColumnNameArray.length) {
					return Integer.compare(o1.getColumnName().length(), o2.getColumnName().length());
				} else {
					return Integer.compare(o1ColumnNameArray.length, o2ColumnNameArray.length);
				}
			}
		}
	};

	/**
	 * 拆分字段名<br/>
	 * 将字段名按照大写字母和下划线分割成多个部分。<br/>
	 * 例如，对于字段名"colName_Abc_def"，将返回一个数组，包含["colName", "Abc", "def"]。<br/>
	 *
	 * @param columnName 待拆分的字段名
	 * @return 拆分后的字段名部分组成的数组
	 */
	private static String[] splitColumeName(String columnName) {
		// 将大写字母前添加逗号，以便分割；同时将下划线替换为逗号
		String columnNameArraySource = columnName;
		columnNameArraySource = columnNameArraySource.replaceAll("[A-Z]", ",$0");
		columnNameArraySource = columnNameArraySource.replaceAll("_", ",");
		// 使用逗号分割字段名字符串，并返回分割后的数组
		String[] columnNameArray = StringUtils.splitByWholeSeparator(columnNameArraySource, ",");
		return columnNameArray;
	}

	/**
	 * 根据字段名解析对象<br/>
	 * 此方法用于根据给定的属性描述器和列名，解析出嵌套属性描述器。主要用于处理非简单类型的属性，例如对象或数组等。
	 *
	 * @param propertyDescriptor 属性描述器，描述了目标对象的一个属性。
	 * @param columnName         列名，需要解析成属性描述器的字符串。
	 * @return 返回解析出的嵌套属性描述器，如果无法解析则返回null。
	 */
	private static PropertyDescriptor parseCustomizeTypeNestedPropertyDescriptorByColumnName(
			PropertyDescriptor propertyDescriptor, String columnName) {
		// 确保输入的属性描述器和列名不为空
		AssertUtils.notNull(propertyDescriptor, "propertyDescriptor is null.");
		AssertUtils.notEmpty(columnName, "columnName is empty.");

		Class<?> propertyType = propertyDescriptor.getPropertyType(); // 获取属性类型
		String propertyName = propertyDescriptor.getName(); // 获取属性名称

		// 确保属性类型不是简单类型，也不是集合、Map或数组
		AssertUtils.isTrue(!BeanUtils.isSimpleValueType(propertyType), "propertyType:{} is not simpleValueType.",
				new Object[] { propertyDescriptor.getPropertyType() });
		AssertUtils.isTrue(
				!propertyType.isArray() && !Collection.class.isAssignableFrom(propertyType)
						&& !Map.class.isAssignableFrom(propertyType),
				"propertyType:{} is Array or Abstract or Collection or Map.",
				new Object[] { propertyDescriptor.getPropertyType() });

		String nestedPropertyName = null;
		// 判断列名是否为属性名的一部分或通过列名的分割获取嵌套属性名
		if (columnName.length() > propertyName.length() && columnName.indexOf("_") < 0 // 字段中如果含有"_"则优先根据拆分办法进行取值
				&& StringUtils.startsWithIgnoreCase(columnName, propertyName)) {
			// 如果属性名是字段名的一部分采用该截取的方式获取字段名
			nestedPropertyName = StringUtils.substring(columnName, propertyName.length());
		} else if (!StringUtils.equalsIgnoreCase(columnName, propertyName)) {
			// 取字段名数组中最后一个字符串
			String columnNameArraySource = columnName;
			columnNameArraySource = columnNameArraySource.replaceAll("[A-Z]", ",$0");
			columnNameArraySource = columnNameArraySource.replaceAll("_", ",");
			String[] columnNames = StringUtils.splitByWholeSeparator(columnNameArraySource, ",");

			// 确保分割后的字段名数组长度大于1
			AssertUtils.isTrue(columnNames.length > 1, "columnNames:{} length should > 1.",
					new Object[] { columnNames });
			nestedPropertyName = columnNames[columnNames.length - 1];
		} else {
			// 如果列名与属性名完全一致，或无法通过上述方式解析，则返回null
			return null;
		}

		// 确保解析出的嵌套属性名不为空
		AssertUtils.notEmpty(nestedPropertyName, "parse nestedPropertyName error.nestedPropertyName is empty.");

		// 将嵌套属性名的首字母转为小写，以符合Java属性的命名规范
		nestedPropertyName = StringUtils.uncapitalize(nestedPropertyName);
		PropertyDescriptor nestedPropertyDescriptor = BeanUtils.getPropertyDescriptor(propertyType, nestedPropertyName);

		// 尝试从属性类型中获取嵌套属性描述器，如果未找到则遍历所有属性描述器查找匹配的
		if (nestedPropertyDescriptor == null) {
			for (PropertyDescriptor pdTemp : BeanUtils.getPropertyDescriptors(propertyType)) {
				if (StringUtils.equalsIgnoreCase(pdTemp.getName(), nestedPropertyName)) {
					nestedPropertyDescriptor = pdTemp;
					break;
				}
			}
		}
		// 确保最终找到了嵌套属性描述器，并且该属性的类型为简单类型
		AssertUtils.notNull(nestedPropertyDescriptor, "nestedPropertyDescriptor is null.nestedPropertyName:{} ",
				nestedPropertyName);
		AssertUtils.isTrue(BeanUtils.isSimpleValueType(nestedPropertyDescriptor.getPropertyType()),
				"nestedProperty " + "should is simpleValueType.but actual is :{}",
				new Object[] { nestedPropertyDescriptor.getPropertyType() });

		return nestedPropertyDescriptor;
	}
}
